<template>
    <div class="filter">
        <div v-if="showFilter" class="condition">
            <span class="split"></span>
            <div class="condition-option">
                <a-button class="condition-button" v-on:click="switchCondition()" >{{ conditionLabel }}</a-button>
            </div>
        </div>
        <div class="filter-items">
            <div v-for="(item, index) in filter.filterItems" :key="item.key">
                <Rule :disabled="disabled" v-if="item.type === 0" v-model="item.value" v-bind:datasourceId="datasourceId" v-bind:index="index" v-bind:properties="properties" v-bind:virtual="virtual" v-bind:group="canAddGroup" v-on:add="addRule" v-on:add-group="addFilter" v-on:remove="removeRule"></Rule>
                <MultiLevelFilter :disabled="disabled" v-if="item.type === 1" v-model="item.value" v-bind:index="index" v-bind:properties="properties" v-bind:virtual="virtual" v-bind:datasourceId="datasourceId" v-on:remove="demote"></MultiLevelFilter>
            </div>
        </div>
    </div>
</template>

<script>
    import Rule from "./Rule";
    import { compareObject } from "@/components/CompareUtils";

    export default {
        name: "MultiLevelFilter",
        components: {
            Rule
        },
        props: {
            value: Object,
            properties: Array,
            datasourceId: {
              type: Number,
              default: null
            },
            isRoot: {
              type: Boolean,
              default: false
            },
            index: {
                type: Number,
                default: 0
            },
            virtual: {
                type: Boolean,
                default: false
            },
            disabled: {
                type: Boolean,
                default: false
            }
        },
        data() {
            return {
                filter: {
                    condition: "",
                    filterItems: []
                },
            }
        },
        computed: {
            showFilter: function () {
                return (this.filter.condition === "AND" || this.filter.condition === "OR") && this.filter.filterItems.length > 1;
            },
            conditionLabel: function () {
                if(this.showFilter) {
                    const conditionLabels = {
                        "AND": "且",
                        "OR": "或"
                    };
                    return conditionLabels[this.filter.condition];
                }
                return "";
            },
            canAddGroup: function() {
                return !(this.value.rules.length === 1 && this.value.filters.length === 0);
            }
        },
        methods: {
            //切换条件组关系，支持且、或两种关系
            switchCondition: function() {
                // 根节点不能切换
                if (this.isRoot) {
                    return;
                }
                if(this.filter.condition === 'AND') {
                    this.filter.condition = 'OR';
                } else if(this.filter.condition === 'OR') {
                    this.filter.condition = 'AND';
                }
            },
            //由于v-for中无法通过v-mode直接绑定数组元素，因此将filter包装到一个对象中
            wrapFilter: function(filter) {
                let obj = {};
                obj.key = filter.index;
                // 组件类型：0-Rule，1-MultiLevelFilter
                obj.type = 1;
                obj.value = {
                    condition: filter.condition,
                    rules: filter.rules,
                    filters: filter.filters
                };
                return obj;
            },
            //由于v-for中无法通过v-mode直接绑定数组元素，因此将rule包装到一个对象中
            wrapRule: function(rule) {
                let obj = {};
                obj.key = rule.index;
                // 组件类型：0-Rule，1-MultiLevelFilter
                obj.type = 0;
                obj.value = {
                    property: rule.property,
                    operator: rule.operator,
                    values: rule.values,
                    value: rule.value
                };
                return obj;
            },
            //初始化data中的filter
            initFilter: function(value) {
                if(!value) {
                    return;
                }
                this.filter.condition = value.condition;
                this.filter.filterItems.splice(0, this.filter.filterItems.length);
                if(value.rules && value.rules.length > 0) {
                    for(let i = 0; i < value.rules.length; i++) {
                        this.filter.filterItems.push(this.wrapRule(value.rules[i]));
                    }
                }
                if(value.filters && value.filters.length > 0) {
                    for(let i = 0; i < value.filters.length; i++) {
                        this.filter.filterItems.push(this.wrapFilter(value.filters[i]));
                    }
                }
                this.filter.filterItems.sort(function(a, b) {
                    return a.key - b.key;
                });
            },
            //将value对象转换为filter结构对象
            transformFilter: function(value) {
                let filter = {
                    condition: "",
                    filterItems: []
                };
                filter.condition = value.condition;
                filter.filterItems.splice(0, filter.filterItems.length);
                if (value.rules && value.rules.length > 0) {
                    for (let i = 0; i < value.rules.length; i++) {
                        filter.filterItems.push(this.wrapRule(value.rules[i]));
                    }
                }
                if (value.filters && value.filters.length > 0) {
                    for (let i = 0; i < value.filters.length; i++) {
                        filter.filterItems.push(this.wrapFilter(value.filters[i]));
                    }
                }
                filter.filterItems.sort(function (a, b) {
                    return a.key - b.key;
                });
                return filter;
            },
            //将filter对象转换为value对象
            transformValue: function (filter) {
                let value = {
                    index: this.index,
                    condition: filter.condition,
                    rules: [],
                    filters: []
                };
                if(filter.condition === "AND" || filter.condition === "OR") {
                    for(let i = 0; i < filter.filterItems.length; i++) {
                        let item = {
                            index: i
                        };
                        item = Object.assign(item, filter.filterItems[i].value);
                        if(item.condition === "AND" || item.condition === "OR") {
                            value.filters.push(item);
                        } else {
                            value.rules.push(item);
                        }
                    }
                } else {
                    let item = {
                        index: 0
                    };
                    item = Object.assign(item, filter.filterItems[0].value);
                    value.rules.push(item);
                }
                return value;
            },
            //添加筛选条件
            addRule: function () {
                let rule = {
                    key: this.filter.filterItems.length,
                    type: 0,
                    value: {
                        property: "",
                        operator: "",
                        values: [],
                        value: ""
                    }
                };
                this.filter.filterItems.push(rule);
            },
            //新增一个空条件与原有的筛选条件一起组成一个条件组
            addFilter: function(index) {
                let filter = this.filter.filterItems[index];
                filter.type = 1;
                let rule = filter.value;
                //将原来的rule转为filter
                filter.value = {
                    condition: "AND",
                    rules: [],
                    filters: []
                };
                //将原来的rule加入到新filter中的rules中，作为第一项
                rule.index = 0;
                filter.value.rules.push(rule);
                //在新filter的rules中追加第二项
                filter.value.rules.push({
                    index: 1,
                    property: "",
                    operator: "",
                    values: [""],
                    value: ""
                });
                this.filter.filterItems.splice(index, 1, filter);
            },
            //删除筛选条件
            removeRule: function (index) {
                this.filter.filterItems.splice(index, 1);
                if(this.filter.filterItems.length <= 1) {
                    //等待组件数据更新完成后，再通知父组件，否则父组件会基于旧数据进行操作
                    this.$nextTick(()=> {
                        this.$emit("remove", this.index);
                    });
                }
            },
            //条件组降级：如果条件组只剩一个条件，那么移除当前条件组，将剩下的这个条件合并到上级条件组中。
            demote: function (index) {
                let item = this.filter.filterItems[index];
                let filter = this.transformFilter(item.value);
                if (filter.filterItems.length > 0) {
                    let filterItem = filter.filterItems[0];
                    item.type = filterItem.type;
                    item.value = filterItem.value;
                    this.filter.filterItems.splice(index, 1, item);
                }
            },
        },
        watch: {
            filter: {
                handler(newVal, oldVal) {
                    let value = this.transformValue(newVal);
                    if(!compareObject(value, this.value)) {
                        this.$emit("input", this.transformValue(newVal))
                    }
                },
                deep: true
            },
            value: {
                handler(newVal, oldVal) {
                    if(!compareObject(newVal, this.transformValue(this.filter))) {
                        this.initFilter(newVal);
                    }
                },
                deep: true
            }
        },
        mounted() {
            this.initFilter(this.value);
        }
    }
</script>

<style scoped>
    .filter {
        display: flex;
        justify-content: flex-start;
        width: 100%;
        background-color: rgb(247, 247, 247);
    }
    .filter .condition {
        display: flex;
        align-items: center;
        justify-content: center;
        box-sizing: border-box;
        padding: 5px 5px;
    }
    .filter .condition .split {
        display: inline-block;
        width: 2px;
        /*background: #e9f0f7;*/
        background: #2d8cf0;
        height: 100%;
        position: relative;
        left: 17px;
    }
    .filter .condition .condition-option {
        position: relative;
        z-index: 9;
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-direction: column;
        border-radius: 2px;
    }
    .filter .condition .condition-option .condition-button {
        cursor: pointer;
        padding: 4px 8px;
        border: 1px solid rgb(200, 200, 200);
        background-color: rgb(245, 245, 245);
        border-radius: 3px;
    }
    .filter .filter-items {
        flex: 1;
      margin-left: 10px;
    }
</style>
